#ifndef mixer
#define mixer
#include <vector>
#include <cstdio>
#include <vector>
#include <arpa/inet.h>


const signed short nosound=0;

template <class SoundSource>
class Mixer{
    public:
        std::vector<SoundSource*> sources;
        /*
         * The format of the sound to be mix should be 16-bit signed interger big endian
         *
         * length: in bytes
         */
        void readSound(char* readto_address,int length){
            std::vector<SoundSource*> valid_sources;
            for(typename std::vector<SoundSource*>::iterator source=this->sources.begin();source!=this->sources.end();source++){
                SoundSource *s=*source;
                if(s->valid()){
                    //Still left something to read
                    valid_sources.push_back(*source);
                }
            }

            signed short* short_readto_addr=(signed short*)readto_address;
            unsigned long sources_count=valid_sources.size();
            if(sources_count==0){
                int packet_count=length/2;
                for(int i=0;i<packet_count;i++){
                    short_readto_addr[i]=nosound;
                }
                return;
            }

            int packet_count=length/2;
            signed short *mixBuffer=new short[sources_count*packet_count];
            for(unsigned int source_index=0;source_index<sources_count;source_index++){
                valid_sources[source_index]->readSound(((char*)mixBuffer)+source_index*length,length);
            }

            signed int tmp_sum=0; //Plenty of headroom!
            for(int packet_index=0;packet_index<packet_count;packet_index++){
                tmp_sum=0;
                for(unsigned int source_index=0;source_index<sources_count;source_index++){
                    signed short val=ntohs(mixBuffer[source_index*packet_count+packet_index]);
                    tmp_sum+=val;
                }
                tmp_sum/=sources_count;
                short_readto_addr[packet_index]=htons(tmp_sum);
            }
            delete [] mixBuffer;
        };
        void addSource(SoundSource *source){
            this->sources.push_back(source);
        };
};
#endif
